package algotrader.book;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class BookManager {
	private BookRequester fixApp;
	
	private Map<String,List<BookManagerObserver>> bmo;
	private Map<String,List<BookManagerObserver>> pendentes;
	private Map<String,Book> books;
	
	public BookManager() {
		bmo =  new HashMap<String,List<BookManagerObserver>>();
		pendentes =  new HashMap<String,List<BookManagerObserver>>();
		books = new HashMap<String,Book>();
	}
	
	public void setFixApplication(BookRequester fixApp) {
		this.fixApp = fixApp;
	}

	public void requestBook(String string, BookManagerObserver bmo) {
		if(books.containsKey(string)) {
			this.bmo.get(string).add(bmo);
			bmo.receiveBook(books.get(string));
		} else {
			if(!this.pendentes.containsKey(string))
				this.pendentes.put(string, new ArrayList<BookManagerObserver>());
			this.pendentes.get(string).add(bmo);
			
			if(this.pendentes.get(string).size()==1)
				fixApp.requestBook(string,this);
		}
	}

	public void receiveBook(Book book) {
		books.put(book.getAtivo(), book);
		
		for(BookManagerObserver bmo : this.pendentes.get(book.getAtivo()))
			bmo.receiveBook(book);
		
		if(!bmo.containsKey(book.getAtivo())) 
			bmo.put(book.getAtivo(), new ArrayList<BookManagerObserver>());
		
		bmo.get(book.getAtivo()).addAll(pendentes.get(book.getAtivo()));
		pendentes.get(book.getAtivo()).clear();
	}

	public void receiveBookLine(BookLine bookLine) {
		books.get(bookLine.getAtivo()).addBookLine(bookLine);
		for(BookManagerObserver bmo : this.bmo.get(bookLine.getAtivo()))
			bmo.receiveBookLine(bookLine);
	}

	public void removeObserver(String string, BookManagerObserver bmo) {
		if(this.bmo.containsKey(string))
			this.bmo.get(string).remove(bmo);
	}

	public List<BookManagerObserver> getObservers(String string) {
		return this.bmo.get(string);
	}

	public List<BookManagerObserver> getPendentes(String string) {
		return pendentes.get(string);
	}
	
	public boolean containsPendente(String ativo, BookManagerObserver bmo) {
		try {
			return pendentes.get(ativo).contains(bmo);
		} catch (NullPointerException e) {
			return false;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}
	
	public boolean containsObserver(String ativo, BookManagerObserver bmo) {
		try {
			return this.bmo.get(ativo).contains(bmo);
		} catch (NullPointerException e) {
			return false;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	public void removeBookLine(BookLine bookLine) {
		books.get(bookLine.getAtivo()).removeBookLine(bookLine);
		for(BookManagerObserver bmo : this.bmo.get(bookLine.getAtivo()))
			bmo.removeBookLine(bookLine);
	}

	public void receiveBookLines(List<BookLine> bls) {
		books.get(bls.get(0).getAtivo()).addBookLines(bls);
		for(BookManagerObserver bmo : this.bmo.get(bls.get(0).getAtivo()))
			bmo.receiveBookLines(bls);
	}

	public Book getBook(String ativo) {
		return books.get(ativo);
	}
}
